#include "../pch.hpp"

#include "core_common/ngt_windows.hpp"
#include "core_serialization/file_system.hpp"
#include <unistd.h>
#include <sys/stat.h>

namespace wgt
{
TEST(file_sytem)
{
	FileSystem fileSystem;

	char const* filePath = "TestFile.txt";
	char const* testData = "Uni, arch toressful, Could insits bervit of a pren, Abutio, yethis tassion, \
													to to les wity winet uponeus, licitly of be act it, Hiss, is himent the God's \
													joyalti-datche imusin a forine), ways knoth ne caught not rience, wer reat meorin \
													Here of ses of con ch conses our mandif Pal to expeat usives takescie infata he of \
													scup who . – generated by Just Another Test Text Generator";

	size_t testDataLength = strlen(testData);
	if (fileSystem.exists(filePath))
		fileSystem.remove(filePath);

	char wdir[PATH_MAX];
	CHECK(getwd(wdir) != nullptr);
	CHECK(fileSystem.exists(wdir) == true);
	CHECK(fileSystem.getFileInfo(wdir)->isDirectory());
	CHECK(fileSystem.getFileType(wdir) == IFileSystem::Directory);

	CHECK(fileSystem.exists(filePath) == false);
	CHECK(fileSystem.writeFile(filePath, testData, testDataLength, std::ios::trunc | std::ios::out));
	CHECK(fileSystem.exists(filePath) == true);

	IFileSystem::IStreamPtr stream = fileSystem.readFile(filePath, std::ios::in);
	CHECK(stream->size() == testDataLength);
	char* readedData = (char*)malloc(stream->size());
	size_t readedSize = stream->readRaw(readedData, stream->size());
	CHECK(readedSize == stream->size());
	stream = nullptr;

	memcmp(testData, readedData, testDataLength);

	CHECK(fileSystem.getFileType(filePath) == IFileSystem::FileType::File);
	CHECK(fileSystem.getFileType("dummy") == IFileSystem::FileType::NotFound);

	char const* movedFilePath = "MovedTestFile.txt";
	CHECK(fileSystem.move(filePath, movedFilePath));
	CHECK(fileSystem.exists(filePath) == false);
	CHECK(fileSystem.exists(movedFilePath) == true);

	CHECK(fileSystem.copy(movedFilePath, filePath));
	CHECK(fileSystem.exists(filePath) == true);
	CHECK(fileSystem.exists(movedFilePath) == true);

	CHECK(fileSystem.remove(movedFilePath));
	CHECK(fileSystem.exists(filePath) == true);
	CHECK(fileSystem.exists(movedFilePath) == false);

	IFileInfoPtr info = fileSystem.getFileInfo(filePath);
	CHECK(fileSystem.exists(info->fullPath()) == true);

	int counter = 0;
	fileSystem.enumerate(wdir, [&](IFileInfoPtr&& info) {
		CHECK(fileSystem.exists(info->fullPath()));
		CHECK(fileSystem.getFileInfo(info->fullPath())->size() == info->size());
		++counter;
		return true;
	});

	CHECK(counter != 0);

	CHECK(fileSystem.remove(filePath));

	char userDirectoryPath[MAX_PATH];
	CHECK(GetUserDirectoryPath(userDirectoryPath));
	CHECK(fileSystem.exists(userDirectoryPath));

	std::string userToolsPath = userDirectoryPath;
	userToolsPath += FilePath::kNativeDirectorySeparator;
	userToolsPath += "wgtools_testing";

	if (fileSystem.exists(userToolsPath.c_str()))
	{
		rmdir(userToolsPath.c_str());
	}

	CHECK(!fileSystem.exists(userToolsPath.c_str()));
	CHECK(CreateDirectoryPath(userToolsPath.c_str()));
	CHECK(fileSystem.exists(userToolsPath.c_str()));
	CHECK(CreateDirectoryPath(userToolsPath.c_str())); // Ensure multiple calls return true
	CHECK(rmdir(userToolsPath.c_str()) == 0);
	CHECK(!fileSystem.exists(userToolsPath.c_str()));

	free(readedData);
}
} // end namespace wgt
